import threading
import queue
import time
from concurrent.futures import ThreadPoolExecutor
from django.utils import timezone
from django.conf import settings
import uuid

class TaskManager:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(TaskManager, cls).__new__(cls)
            cls._instance.initialize()
        return cls._instance
    
    def initialize(self):
        self.tasks = {}
        self.task_lock = threading.Lock()
        # 创建线程池，大小可在settings中配置
        max_workers = getattr(settings, 'TASK_MAX_WORKERS', 5)
        self.executor = ThreadPoolExecutor(max_workers=max_workers)
        # 启动定期清理任务
        self._start_cleanup_thread()
    
    def _start_cleanup_thread(self):
        """启动定期清理旧任务的线程"""
        def cleanup_worker():
            while True:
                try:
                    self.clean_old_tasks()
                except Exception as e:
                    print(f"清理任务出错: {str(e)}")
                time.sleep(3600)  # 每小时清理一次
        
        cleanup_thread = threading.Thread(target=cleanup_worker, daemon=True)
        cleanup_thread.start()
    
    def _task_callback(self, future, task_id):
        """任务完成后的回调函数"""
        with self.task_lock:
            try:
                result = future.result()
                self.tasks[task_id].update({
                    'status': 'completed',
                    'result': result,
                    'progress': 100,  # 设置完成进度
                    'end_time': timezone.now()
                })
            except Exception as e:
                self.tasks[task_id].update({
                    'status': 'failed',
                    'error': str(e),
                    'progress': 0,  # 重置进度
                    'end_time': timezone.now()
                })
    
    def submit_task(self, func, *args, **kwargs):
        """提交任务到线程池"""
        task_id = str(uuid.uuid4())
        
        with self.task_lock:
            self.tasks[task_id] = {
                'status': 'pending',  # 初始状态为 pending
                'create_time': timezone.now(),
                'function': func.__name__,
                'args': args,
                'kwargs': kwargs
            }
        
        future = self.executor.submit(func, *args, **kwargs)
        future.add_done_callback(lambda f: self._task_callback(f, task_id))
        
        return task_id
    
    def get_task_status(self, task_id):
        """获取任务状态"""
        with self.task_lock:
            task = self.tasks.get(task_id)
            if task:
                # 创建一个新的字典，只返回需要的信息
                return {
                    'status': task['status'],
                    'create_time': task['create_time'],
                    'error': task.get('error', ''),
                    'result': task.get('result', None),
                    'end_time': task.get('end_time', None)
                }
            return None
    
    def get_recent_tasks(self, limit=10):
        """获取最近的任务"""
        with self.task_lock:
            tasks = list(self.tasks.items())
            tasks.sort(key=lambda x: x[1]['create_time'], reverse=True)
            return dict(tasks[:limit])
    
    def clean_old_tasks(self, hours=24):
        """清理旧任务"""
        current_time = timezone.now()
        with self.task_lock:
            old_tasks = [
                task_id for task_id, task in self.tasks.items()
                if (current_time - task['create_time']).total_seconds() > hours * 3600
                and task['status'] in ['completed', 'failed']
            ]
            for task_id in old_tasks:
                del self.tasks[task_id]
    
    def cancel_task(self, task_id):
        """取消正在执行的任务（如果可能）"""
        with self.task_lock:
            if task_id in self.tasks and self.tasks[task_id]['status'] == 'running':
                self.tasks[task_id]['status'] = 'cancelled'
                return True
        return False
    
    def get_active_tasks_count(self):
        """获取当前活动任务数量"""
        with self.task_lock:
            return sum(1 for task in self.tasks.values() 
                      if task['status'] in ['pending', 'running'])
    
    def shutdown(self):
        """关闭任务管理器"""
        self.executor.shutdown(wait=True)

    def update_task_progress(self, task_id, progress):
        """更新任务进度"""
        with self.task_lock:
            if task_id in self.tasks:
                self.tasks[task_id]['progress'] = progress

# 全局任务管理器实例
task_manager = TaskManager() 